package com.hk.core.data.jpa.listeners;

import com.hk.commons.util.Constants;
import com.hk.commons.util.ObjectUtils;
import com.hk.commons.util.SpringContextHolder;
import com.hk.core.data.jpa.domain.DelectionPersistable;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreRemove;
import jakarta.persistence.PreUpdate;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.data.domain.AuditorAware;

import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Optional;


/**
 * @see DelectionPersistable
 */
@Configurable
public class DelectionEntityListener {

    @PrePersist
    public void touchForCreate(Object target) {
        if (target instanceof DelectionPersistable<?> delectionPersistable) {
            Boolean deletedState = delectionPersistable.getDeletedState();
            if (Objects.isNull(deletedState)) {
                delectionPersistable.setDeletedState(Boolean.FALSE);
            }
            this.fillProps(delectionPersistable);
        }
    }

    @PreUpdate
    public void touchForUpdate(Object target) {
        if (target instanceof DelectionPersistable<?> persistable) {
            this.fillProps(persistable);

        }
    }

    private void fillProps(DelectionPersistable persistable) {
        LocalDateTime deletedDate = null;
        Object deletedBy = null;
        if (Boolean.TRUE.equals(persistable.getDeletedState())) {
            deletedDate = ObjectUtils.defaultIfNull(persistable.getDeletedDate(), LocalDateTime.now());
            deletedBy = persistable.getDeletedBy();
            if (Objects.isNull(deletedBy)) {
                AuditorAware<?> auditorAware = SpringContextHolder.getBeanIfExist(AuditorAware.class).orElse(null);
                deletedBy = Optional.ofNullable(auditorAware).flatMap(AuditorAware::getCurrentAuditor).orElse(null);
                deletedBy = ObjectUtils.defaultIfNull(deletedBy, Constants.DEFAULT_VALUE_LONG);
            }
        }
        persistable.setDeletedDate(deletedDate);
        persistable.setDeletedBy(deletedBy);
    }

    @PreRemove
    public void touchForDelete(Object target) {
        if (target instanceof DelectionPersistable<?> persistable) {
            persistable.setDeletedState(Boolean.TRUE);
            this.fillProps(persistable);
        }
    }
}
